<!-- TabsComponent.vue -->
<template>
  <div class="tabs-container">
    <!-- 标签导航 -->
    <div class="tabs-nav-wrapper" ref="navWrapper">
      <div class="tabs-nav" ref="nav">
        <div
          v-for="(tab, index) in tabs"
          :key="tab.key"
          :ref="(el) => setTabRef(el, index)"
          class="tab-item"
          :class="{ active: activeKey === tab.key, disabled: tab.disabled }"
          @click="handleTabClick(tab, index)"
        >
          <span class="tab-label">{{ tab.label }}</span>
          <span 
            v-if="tab.tag" 
            class="tab-tag"
            :class="`tab-tag--${tab.tag.type || 'default'}`"
            :style="{ backgroundColor: tab.tag.color }"
          >
            {{ tab.tag.text }}
          </span>
          <span v-if="tab.closable" class="tab-close" @click.stop="handleClose(tab, index)">
            ×
          </span>
        </div>
      </div>
    </div>

    <!-- 内容区域 -->
    <div class="tabs-content" ref="contentWrapper">
      <div
        class="tabs-content-inner"
        :style="{
          transform: `translateX(-${activeIndex * 100}%)`,
          transition: 'transform 0.3s ease'
        }"
      >
        <div
          v-for="tab in tabs"
          :key="tab.key"
          class="tab-pane"
        >
          <slot :name="`tab-pane-${tab.key}`" :tab="tab">
            <div class="default-content">
              {{ tab.content || `Content for ${tab.label}` }}
            </div>
          </slot>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick, onMounted } from 'vue'

export interface TabItem {
  key: string | number
  label: string
  content?: string
  disabled?: boolean
  closable?: boolean
  tag?: {
    text: string
    type?: 'default' | 'primary' | 'success' | 'warning' | 'danger'
    color?: string
  }
}

interface Props {
  tabs: TabItem[]
  type?: 'line' | 'card'
  size?: 'small' | 'medium' | 'large'
  animated?: boolean
  swipeable?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  type: 'line',
  size: 'medium',
  animated: true,
  swipeable: true
})

const activeKey = defineModel<string | number>('activeKey')

const emit = defineEmits<{
  'tab-click': [tab: TabItem, index: number]
  'tab-close': [tab: TabItem, index: number]
  'change': [activeKey: string | number, prevKey: string | number]
}>()

// 处理默认值
if (!activeKey.value && props.tabs.length > 0) {
  activeKey.value = props.tabs[0].key
}

const activeIndex = computed(() => 
  props.tabs.findIndex(tab => tab.key === activeKey.value)
)

const navWrapper = ref<HTMLElement>()
const nav = ref<HTMLElement>()
const contentWrapper = ref<HTMLElement>()
const tabRefs = ref<HTMLElement[]>([])

const setTabRef = (el: any, index: number) => {
  if (el) {
    tabRefs.value[index] = el
  }
}

// 处理标签点击
const handleTabClick = (tab: TabItem, index: number) => {
  if (tab.disabled) return
  
  const prevKey = activeKey.value
  activeKey.value = tab.key
  emit('tab-click', tab, index)
  
  if (prevKey !== tab.key) {
    emit('change', tab.key, prevKey)
  }
  
  scrollToTab(index)
}

// 处理关闭标签
const handleClose = (tab: TabItem, index: number) => {
  emit('tab-close', tab, index)
}

// 滚动到指定标签
const scrollToTab = async (index: number) => {
  if (!navWrapper.value || !nav.value) return
  
  await nextTick()
  
  const tabElement = tabRefs.value[index]
  if (!tabElement) return
  
  const navRect = navWrapper.value.getBoundingClientRect()
  const tabRect = tabElement.getBoundingClientRect()
  
  const scrollLeft = nav.value.scrollLeft
  const tabLeft = tabRect.left - navRect.left + scrollLeft
  const tabWidth = tabRect.width
  
  const navWidth = navRect.width
  
  if (tabLeft < scrollLeft) {
    // 标签在左边，需要向左滚动
    nav.value.scrollTo({
      left: tabLeft - 20,
      behavior: 'smooth'
    })
  } else if (tabLeft + tabWidth > scrollLeft + navWidth) {
    // 标签在右边，需要向右滚动
    nav.value.scrollTo({
      left: tabLeft + tabWidth - navWidth + 20,
      behavior: 'smooth'
    })
  }
}

// 监听标签页变化
watch(() => props.tabs, () => {
  if (!props.tabs.find(tab => tab.key === activeKey.value)) {
    activeKey.value = props.tabs[0]?.key
  }
}, { deep: true })

// 触摸滑动支持
let startX = 0
let currentX = 0
let isDragging = false

const handleTouchStart = (e: TouchEvent) => {
  if (!props.swipeable) return
  startX = e.touches[0].clientX
  isDragging = true
}

const handleTouchMove = (e: TouchEvent) => {
  if (!isDragging || !props.swipeable) return
  currentX = e.touches[0].clientX
}

const handleTouchEnd = () => {
  if (!isDragging || !props.swipeable) return
  isDragging = false
  
  const diff = startX - currentX
  const threshold = 50
  
  if (Math.abs(diff) > threshold) {
    if (diff > 0 && activeIndex.value < props.tabs.length - 1) {
      // 向左滑动，下一个标签
      const nextTab = props.tabs[activeIndex.value + 1]
      if (!nextTab.disabled) {
        handleTabClick(nextTab, activeIndex.value + 1)
      }
    } else if (diff < 0 && activeIndex.value > 0) {
      // 向右滑动，上一个标签
      const prevTab = props.tabs[activeIndex.value - 1]
      if (!prevTab.disabled) {
        handleTabClick(prevTab, activeIndex.value - 1)
      }
    }
  }
}

onMounted(() => {
  if (props.swipeable && contentWrapper.value) {
    contentWrapper.value.addEventListener('touchstart', handleTouchStart)
    contentWrapper.value.addEventListener('touchmove', handleTouchMove)
    contentWrapper.value.addEventListener('touchend', handleTouchEnd)
  }
})

// 公共方法
const scrollToActiveTab = () => {
  scrollToTab(activeIndex.value)
}

defineExpose({
  scrollToActiveTab,
  activeKey,
  activeIndex
})
</script>

<style scoped lang="scss">
.tabs-container {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #fff;
}

.tabs-nav-wrapper {
  position: relative;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE 10+ */
  
  &::-webkit-scrollbar {
    display: none; /* Chrome Safari */
  }
}

.tabs-nav {
  display: flex;
  align-items: center;
  min-width: max-content;
  padding: 0 16px;
  border-bottom: 1px solid #e8e8e8;
}

.tab-item {
  position: relative;
  padding: 12px 16px;
  cursor: pointer;
  user-select: none;
  transition: all 0.3s ease;
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
  
  &:hover {
    color: #1890ff;
  }
  
  &.active {
    color: #1890ff;
    font-weight: 500;
    
    &::after {
      content: '';
      position: absolute;
      bottom: -1px;
      left: 0;
      right: 0;
      height: 2px;
      background: #1890ff;
    }
  }
  
  &.disabled {
    color: #ccc;
    cursor: not-allowed;
    
    &:hover {
      color: #ccc;
    }
  }
}

.tab-tag {
  display: inline-block;
  padding: 2px 6px;
  font-size: 12px;
  line-height: 1.2;
  border-radius: 10px;
  color: #fff;
  font-weight: 500;
  margin-left: 4px;
  
  &--default {
    background-color: #d9d9d9;
    color: #666;
  }
  
  &--primary {
    background-color: #1890ff;
  }
  
  &--success {
    background-color: #52c41a;
  }
  
  &--warning {
    background-color: #faad14;
  }
  
  &--danger {
    background-color: #ff4d4f;
  }
}

.tab-close {
  font-size: 18px;
  line-height: 1;
  padding: 2px;
  border-radius: 2px;
  
  &:hover {
    background: #f0f0f0;
  }
}

.tabs-content {
  flex: 1;
  overflow: hidden;
  position: relative;
}

.tabs-content-inner {
  display: flex;
  height: 100%;
  width: 100%;
}

.tab-pane {
  flex: 0 0 100%;
  height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.default-content {
  padding: 20px;
  color: #666;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .tabs-nav {
    padding: 0 12px;
  }
  
  .tab-item {
    padding: 10px 12px;
    font-size: 14px;
  }
}

/* 主题变量 */
:root {
  --tab-active-color: #1890ff;
  --tab-hover-color: #40a9ff;
  --tab-disabled-color: #ccc;
  --tab-border-color: #e8e8e8;
}
</style>